﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using QxFramework.Core;
using GameMap;
using GameControl;
using System;
public class ItemSyncManager :LogicModuleBase,IItemSyncManager
{
    Dictionary<string, GameObject> itemInstanceDic = new Dictionary<string,GameObject>();
    List<ItemField> activeItemFields = new List<ItemField>();
    public override void Init(object args)
    {
        base.Init(args);
        var tp = GameObject.FindObjectsOfType<Item>();
        foreach(var x in tp)
        {
            if (x.gameObject.activeSelf)
            {
                GameObject.Destroy(x.gameObject);
            }
        }
        MessageManager.Instance.Get<ItemSyncMsg>().RegisterHandler(ItemSyncMsg.ForceSync, (object sender,System.EventArgs e) => {
            LoadActiveItemField();

            SyncItemInstance();
            SyncJoint();
            SyncField();
            SyncItemInfo();
            return null;
        });
        MessageManager.Instance.Get<ItemSyncMsg>().RegisterHandler(ItemSyncMsg.ForceClearExceptPosFixedItem, (object sender, System.EventArgs e) => {

            List<Item> destoryList = new List<Item>();
            var fieldList = activeItemFields;
            foreach (var x in itemInstanceDic)
            {
                if (x.Value.GetComponent<PosFixedItem>() == null)
                {
                    destoryList.Add(x.Value.GetComponent<Item>());
                }
            }
            foreach (var x in destoryList)
            {
                RemoveItem(x);
            }
            return null;
        });
        /*MessageManager.Instance.Get<ItemSyncMsg>().RegisterHandler(ItemSyncMsg.ForceSyncInstance, (object sender, System.EventArgs e) => {
            LoadActiveItemField();

            SyncItemInstance();
            return null;
        });*/
    }
    void RemoveItem(Item x)
    {
        itemInstanceDic.Remove(x.ItemFieldSetting.ItemName);
        GameManager.Get<IItemInstantiateManager>().DestoryItem(x);
    }
    public void SyncField()
    {
        var fieldList = activeItemFields;//GameMap.GameMapManager.Get<IMapManager>().SceneItems;
        for(int i=0;i<fieldList.Count;i++)
        {
            try
            {
                fieldList[i]=itemInstanceDic[fieldList[i].ItemName].GetComponent<Item>().UploadInstanceField();

            }
            catch(Exception e)
            {
                Debug.LogError(e);
            }

        }
        return;
        foreach(var x in itemInstanceDic)
        {
            x.Value.GetComponent<Item>().UploadInstanceField();
        }
    }
    Dictionary<string, Action<Item>> itemActionList=new Dictionary<string, Action<Item>>();
    public void SyncItemInstance()
    {
        var fieldList = activeItemFields;//GameMap.GameMapManager.Get<IMapManager>().SceneItems;
        // var rigidList = new List<ItemRigid>();
        for (int i= 0;i < fieldList.Count;i++)
        {
                var x = fieldList[i];
            if (itemInstanceDic.ContainsKey(x.ItemName) == false|| itemInstanceDic[x.ItemName]==null)
            {
                var item=itemInstanceDic[x.ItemName] = GameManager.Get<IItemInstantiateManager>().CreateItem(x,x).gameObject;

             //   item.GetComponent<Item>().DownloadInstanceField(x);
                item.GetComponent<Item>().OnStart();
                //     itemInstanceDic[x.ItemName].GetComponent<Item>().DownloadInstanceField(x);
            }
            if (itemActionList.ContainsKey(x.ItemName))
            {
                itemActionList[x.ItemName].Invoke(itemInstanceDic[x.ItemName].GetComponent<Item>());
                itemActionList.Remove(x.ItemName);

            }
         /*   var rigid= (itemInstanceDic[x.ItemName].GetComponentInParent<ItemRigid>());
            if (rigid != null)
            {
                rigidList.UniqueAdd<ItemRigid>(rigid);
            }*/
        //    itemInstanceDic[x.ItemName].GetComponent<Item>().Init(x);
        }
    /*    for(int i = 0; i < rigidList.Count; i++)
        {
            rigidList[i].SetRigidInfo();
        }*/
        List<Item> destoryList = new List<Item>();
        foreach(var x in itemInstanceDic)
        {
            if (fieldList.Find(s => s.ItemName == x.Key) == null)
            {
                destoryList.Add(x.Value.GetComponent<Item>());
            }
        }
        foreach(var x in destoryList)
        {
            RemoveItem(x);
        }
    }
    void TryAddJoint(CombinableItem a, CombinableItem b,int fa,int fb)
    {
        if (a.transform.parent != b.transform.parent)
        {
            ItemRigid.Bing(a.GetComponentInParent<ItemRigid>(), b.GetComponentInParent<ItemRigid>());
        }
        /*var tp = a.GetComponents<FixedJoint2D>();
        foreach(var x in tp)
        {
            if (x.connectedBody ==b.GetComponent<Rigidbody2D>())
            {
                return;
            }
        }
        tp = b.GetComponents<FixedJoint2D>();
        foreach (var x in tp)
        {
            if (x.connectedBody == a.GetComponent<Rigidbody2D>())
            {
                return;
            }
        }
        var jo=a.gameObject.AddComponent<FixedJoint2D>();
        jo.enableCollision = false;
        jo.connectedBody = b.GetComponent<Rigidbody2D>();
        //Debug.Log(item + " " + otherRigid + " " + fx);
        Vector3 pos= a.GetLocalDirection(fa*90f);
        pos /= 2.0f;
        pos *= MapManager.itemSize*1.01f;
        Vector3 pos1 =b.GetLocalDirection(fb*90f);
        pos1 /= 2.0f;
        pos1 *= MapManager.itemSize * 1.01f;
        jo.autoConfigureConnectedAnchor = false;
        jo.anchor = pos;
        jo.connectedAnchor = pos1;
        jo.dampingRatio = 1f;
        jo.frequency = 0f;
       // jo.connectedAnchor = (Vector2)pos*-1;*/
    }
    public void SyncJoint()
    {
        var jointList = GameCombine.CombineManager.Get<GameCombine.IItemCombineManager>().ItemJointFields;
        foreach(var x in jointList)
        {
            if(itemInstanceDic.ContainsKey(x.Item[0])==false|| itemInstanceDic.ContainsKey(x.Item[1]) == false)
            {
                continue;
            }
            TryAddJoint(itemInstanceDic[x.Item[0]].GetComponent<CombinableItem>(), itemInstanceDic[x.Item[1]].GetComponent<CombinableItem>(), x.JointPos[0], x.JointPos[1]);
       //     TryAddJoint(itemInstanceDic[x.Item[1]].GetComponent<CombinableItem>(), itemInstanceDic[x.Item[0]].GetComponent<CombinableItem>(), x.JointPos[1], x.JointPos[0]);

        }
    }

    public GameObject GetGameObjectByName(string name)
    {
        if (string.IsNullOrEmpty(name))
        {
            return null;
        }
        if (itemInstanceDic.ContainsKey(name)==false) return null;
        else return itemInstanceDic[name];
    }

    public void SyncItemInfo()
    {
        var fieldList = activeItemFields;//GameMap.GameMapManager.Get<IMapManager>().SceneItems;
        foreach (var x in fieldList)
        {
            try
            {
                itemInstanceDic[x.ItemName].GetComponent<Item>().DownloadInstanceField(x);

            } catch (Exception e)
            {
                Debug.LogError($"{x.ItemName}");
            }

        }
    }

    void IItemSyncManager.ItemFixedUpdateLogic()
    {
        var list = new List<GameObject>();
        foreach (var x in itemInstanceDic) list.Add(x.Value);
        foreach(var x in list)
        {
            if (x.GetComponent<Item>().ItemFieldSetting.IsUpdate)
            {
                x.GetComponent<Item>().FixedUpdateInLogic();

            }
            else
            {
                
            }
        }
    }

    void IItemSyncManager.ItemFixedUpdatePresentation()
    {
        var list = new List<GameObject>();
        foreach (var x in itemInstanceDic) list.Add(x.Value);
        foreach (var x in list)
        {
            if (x.GetComponent<Item>().ItemFieldSetting.IsUpdate)
                x.GetComponent<Item>().FixedUpdateInPresentation();
        }
    }
    public static Vector2 ActiveRange = new Vector2(16, 9);
    public static float ItemRadius = 4;
    bool CheckInRange(Vector2 center,Vector2 point)
    {
        return (Mathf.Abs(center.x - point.x) < ActiveRange.x && Mathf.Abs(center.y - point.y) < ActiveRange.y);
    }
    public void LoadActiveItemField()
    {
        activeItemFields=new List<ItemField>( GameMap.GameMapManager.Get<IMapManager>().SceneItems);
        var cam = GameObject.FindObjectOfType<CameraController>();
        var extra=activeItemFields.FindAll(s => CheckInRange(cam.transform.position, s.Position)==false);
        activeItemFields.RemoveAll(s => CheckInRange(cam.transform.position, s.Position)==false );
        var obj = activeItemFields.FindAll(s => s is CombinableItemField);
        foreach (var x in obj)
        {
            for (int i = 0; i < extra.Count; i++)
            {
                if (Vector2.Distance(x.Position, extra[i].Position) < ItemRadius)
                {
                    activeItemFields.Add(extra[i]);
                    extra.Remove(extra[i]);
                    i--;
                }
            }
        }

   //     Debug.Log(activeItemFields.Count +" "+GameMap.GameMapManager.Get<IMapManager>().SceneItems.Count);

    }

    public void AddItemAction(string name, Action<Item> action)
    {
        if (action != null)
        {
            itemActionList[name] = action;
        }
    }
}
public interface IItemSyncManager
{
    void LoadActiveItemField();
    /// <summary>
    /// 同步物体存在情况
    /// </summary>
    void SyncItemInstance();
    /// <summary>
    /// 同步链接点,要在SyncItem后调用
    /// </summary>
    void SyncJoint();
    /// <summary>
    /// 将物体数据上传
    /// </summary>
    void SyncField();
    /// <summary>
    /// 同步物体数据
    /// </summary>
    void SyncItemInfo();

    void ItemFixedUpdateLogic();

    void ItemFixedUpdatePresentation();

    /// <summary>
    /// 当此物体在添加后第一次被实例化时执行一次
    /// </summary>
    /// <param name="name"></param>
    /// <param name="action"></param>
    void AddItemAction(string name,Action<Item> action);
    /// <summary>
    /// 获取实例物体
    /// </summary>

    GameObject GetGameObjectByName(string name);
}
enum ItemSyncMsg
{
    ForceSync,
    ForceClearExceptPosFixedItem,
 //   ForceSyncInstance
}